#ifndef PROJECT_H__
#define PROJECT_H__

#define GLEW_STATIC
#include <windows.h>
#include <GL/glew.h>
#include <GL/wglew.h>
#include <gl/glu.h>
#include <vector>
#include <map>
#include <string>
#include "FastDelegate.h"	// Header File For Fast Delegates

enum ERROR_ENUM		//Function return values
{
	SOIL_TEX_LOAD_ERROR = -2,
	NULL_FILE_ERROR = -1,
	ALL_OK = 0,
	TEX_LOAD_ERROR = 1,
	GLEW_LOAD_ERROR = 2,
	GL_VERSION_ERROR = 3,
	GL_COULD_NOT_CREATE_VBO_ERROR = 4,
	INCOMPLETE_SCENE_HEADER = 5
};

enum FACE_ENUM		//Faces used in cubemap vbo generation
{
	FRONT = 0,
	TOP = 1,
	RIGHT = 2,
	BOTTOM = 3,
	LEFT = 4,
	BACK = 5
};

enum DRAW_TYPE	//Used for registering draw methods with the renderer
{
	STATIC = GL_STATIC_DRAW,					//Never Updates; called once only, probably.
	UPDATE_IF_DIRTY = GL_DYNAMIC_DRAW,		//Updates per-frame if the VBO has changed - see implementation note
	UPDATE_PER_FRAME = GL_STREAM_DRAW		//Updates every frame
	//To test for mesh dirtiness, the delegate gets called with a null pointer; if the delegate
	//returns true, the VBO is taken to be dirty and the delegate gets called again with a 
	//real pointer. otherwise, it's taken as clean.
	//example code:
	//if(VboVec == NULL){return dirty;}
};

#pragma pack(4)	//so vertexs is align to 4-byte boundries. Floats are 4 bytes.
struct vertex2f
{
	GLfloat u;
	GLfloat v;
	vertex2f()
	{
		u = 0.0f;
		v = 0.0f;
	}
};
#pragma pack(4)
struct vertex3f
{
	GLfloat x;
	GLfloat y;
	GLfloat z;
	vertex3f()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
	}
	void clear(){x = 0; y = 0; z = 0;}
};
#pragma pack(4)
struct vertex4f
{
	GLfloat r;
	GLfloat g;
	GLfloat b;
	GLfloat a;
	vertex4f()
	{
		r = 0.0f;
		g = 0.0f;
		b = 0.0f;
		a = 1.0f;
	}
};
#pragma pack(4)
struct texCoord2f
{
	vertex2f btmLft;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f btmRgt;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f topLft;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f topRgt;	//Constructs to	u, v	= 0.0f, 0.0f
	int TexIndex;		//Not constructed - Base type
};
#pragma pack(4)
struct vertex
{
	vertex3f position;	//Constructs to x, y, z	= 0.0f, 0.0f, 0.0f
	vertex3f normal;	//Constructs to x, y, z	= 0.0f, 0.0f, 0.0f
	vertex2f texCoord;	//Constructs to u, v	= 0.0f, 0.0f
	vertex4f colour;	//Constructs to r,g,b,a = 0.0f, 0.0f, 0.0f, 1.0f
	GLfloat padding[4];	//so struct aligns to 32-byte blocks. Ignored.
};
//used to store vertex attributes for use in VBOs
struct Transform
{
	vertex3f Translation;
	vertex3f Rotation;
};
struct  Cube_Prototype
{
	GLuint Texture[6];
	//Indexes are per-face, as FACE_ENUM 
	//The GLuint is an internal Texture ID, mapped to coords in an atlas by 

	//Texture mapping is performed as follows;
	//The front, back, and side faces all have the y-axis starting at 0 where they touch the
	//bottom face, and 1 where they meet the top face.
	//The x-axes are layed counter-clockwise, so the front face has it's 0,0 in the bottom left corner
	//			   ___
	//            |1  |		This face(Top) has 0,0 at the top vertex of the front face
	// ___ ___ ___|__0|		Thus, its Y axis points away from the front
	//|  1|  1|  1|  1|		Each of these faces have 0,0 at the bottom left
	//|0__|0__|0__|0__|		(Front, Right, Back, Left)
	//|0  |					This face(Bottom) has 0,0 at the bottom left vertex of the front face
	//|__1|					Thus, its Y axis points away from the front

	bool Drawable;
	bool Dangerous;		//If true, kills player on touch
	bool CantTouchThis;	//If true, you can't touch this. It functions as a decorative block.
						//Transparent textures should be used, as the player can walk through it.

	//If Dangerous and CantTouchThis are both on, CantTouchThis will overrule Dangerous
	Cube_Prototype()
	{
		for(int i = 0; i < 6; i++){Texture[i] = 0;}
		Drawable = false;
		Dangerous = false;
		CantTouchThis = false;
	}

};
	struct rectangle
{
	vertex2f btmLft;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f btmRgt;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f topLft;	//Constructs to	u, v	= 0.0f, 0.0f
	vertex2f topRgt;	//Constructs to	u, v	= 0.0f, 0.0f
};

struct TexParseData
{
	std::string TexName;
	std::string TexFile;
	int index;
	texCoord2f TexCoords;

};

struct UI_FILE_ELEMENT
{
	vertex2f btmLft;
	vertex2f size;
	GLuint BGTexture;
	std::vector<GLuint> TypeSpecificNumbers;
	std::string TypeSpecificString;
};

typedef fastdelegate::FastDelegate0<INT>					OpenGLInit_delegate;
typedef fastdelegate::FastDelegate0<Transform>				Transform_delegate;
typedef fastdelegate::FastDelegate1<int, int>				UIStat_delegate;
typedef fastdelegate::FastDelegate1<const char *, int>		TextureLoader_delegate;
typedef fastdelegate::FastDelegate2<GLsizei, GLsizei>		ResizeEvent_delegate;
typedef fastdelegate::FastDelegate3<UINT, WPARAM, LPARAM>	Callback_delegate;
typedef fastdelegate::FastDelegate3<std::vector<vertex> *, const std::map<int, texCoord2f>&, GLuint, bool> DrawEvent_delegate;
typedef std::vector<Callback_delegate>						Callback_group;
typedef GLuint												CUBE_PROTO_INDEX;

struct DrawEventPair
{
	DrawEvent_delegate Draw;
	Transform_delegate Transform;
};

typedef std::vector<DrawEventPair>::iterator	DrawEventIter;

#endif